import React, { useEffect, useState } from 'react';
import { connect } from 'dva';

import { Button, Modal, Steps, Upload, Result, Typography, Radio, message, Spin } from 'antd';
import { UploadFile, UploadProps } from 'antd/es/upload/interface';
import { RadioChangeEvent } from 'antd/es/radio/interface';
import { CloudUploadOutlined } from '@ant-design/icons';
import * as XLSX from 'xlsx';

import { getToken, downloadFileByUrl, getMd5 } from '@/utils/utils';
import { ResponseInterface } from './types';
import { getOptAuthHeaders } from '@/utils/common';

const { Dragger } = Upload;
const { Step } = Steps;
const { Paragraph, Text } = Typography;

interface AbnormalDetail {
  vin?: string;
  reason?: string; //  失败原因
}

interface ImportResponse {
  normalTotal?: number;
  abnormalTotal: number; //  异常条数
  abnormal?: AbnormalDetail[];
  checkResult: 0 | 1; //  数据校验结果0=无异常1=有异常
}

type UploadModalProps = {
  modalOpen: boolean;
  dispatch: any;
  closeModal: (refresh?: Boolean) => void;
};

const uploadModal: React.FC<UploadModalProps> = props => {
  const { dispatch, modalOpen, closeModal } = props;

  const [currentStep, setCurrentStep] = useState(0);
  const [fileList, setFileList] = useState<UploadFile[]>([]);
  const [importResponse, setImportReponse] = useState<ResponseInterface<ImportResponse>>(); // 上传响应
  const [templateUrl, setTemplateUrl] = useState('');
  const [loading, setLoading] = useState(false);
  //    导入模式，0=清空后新增 1=仅新增
  const [importModel, setImportModel] = useState(0);

  const uploadProps: UploadProps = {
    multiple: false,
    headers: { OptAuthorization: `${getToken()}`, ...getOptAuthHeaders() },
    accept: '.xls,.xlsx,application/vnd.ms-excel',
    maxCount: 1,
    onRemove: file => {
      const index = fileList.indexOf(file);
      const newFileList = fileList.slice();
      newFileList.splice(index, 1);
      setFileList(newFileList);
    },
    beforeUpload: file => {
      if (file.size / 1024 / 1024 > 5) {
        message.error('文件大小不得大于5M');
        return false;
      } else {
        const reader = new FileReader();
        reader.onload = e => {
          const data = e.target?.result;
          const workbook = XLSX.read(data, { type: 'binary' });
          const firstSheetName = workbook.SheetNames[0];
          const worksheet = workbook.Sheets[firstSheetName];
          const res = XLSX.utils.sheet_to_json(worksheet, { header: 1 }).slice(1);
          if (res && res.length > 1000) {
            message.error('单次导入的数据不超过1000条');
            setFileList([...fileList]);
          } else {
            setFileList([file]);
          }
        };
        reader.readAsBinaryString(file);
        return false;
      }
    },
    fileList,
    onDrop(e) {
      console.log('拖拽上传文件：', e.dataTransfer.files);
    },
  };

  useEffect(() => {
    dispatch({
      type: 'greyListMng/getData',
      payload: { url: '/common/template/detail', templateCode: 'greyListImportTemplate' },
      callback: (res: ResponseInterface<any>) => {
        setTemplateUrl(res.data?.templateUrl);
      },
    });
  }, []);

  const handleNext = () => {
    // 是否上传了文件
    if (fileList.length < 1) {
      message.error('请上传文件');
      return;
    }
    // 上传
    setLoading(true);
    const formData = new FormData();
    fileList.forEach((file: any) => {
      formData.append('file', file);
    });
    const uploadUrl = `${window.g.url}/gray/management/import?model=${importModel}`;
    fetch(uploadUrl, {
      method: 'POST',
      body: formData,
      headers: { OptAuthorization: `${getToken()}`, ...getOptAuthHeaders(),shaSign: getMd5(`model=${importModel}`) },
    })
      .then(res => res.json())
      .then(res => {
        // setFileList([]);
        setImportReponse(res);
        if (res.statusCode === '0' && res.data?.checkResult === 0) {
          // 成功调用，且数据校验结果无异常，跳转到第三步-成功result
          setCurrentStep(2);
        } else {
          setCurrentStep(1);
        }
      })
      .catch(() => {
        message.error('文件上传失败.');
      })
      .finally(() => {
        setLoading(false);
      });
  };

  const handleRetry = () => {
    setCurrentStep(0);
  };

  /**
   * 下载失败原因文件
   */
  const downloadFailureFile = () => {
    const data: { vin: string | undefined; reason: string | undefined }[] = [];
    importResponse?.data?.abnormal?.forEach(({ vin, reason }: AbnormalDetail) => {
      data.push({
        vin,
        reason,
      });
    });
    const header = {
      vin: 'VIN',
      reason: '异常原因',
    };
    const ws = XLSX.utils.json_to_sheet([header, ...data], { skipHeader: true });
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, 'export');
    XLSX.writeFile(wb, '失败原因.xlsx');
  };

  return (
    <Modal
      width={750}
      bodyStyle={{ maxHeight: 'fit-content' }}
      title="车辆批量导入"
      visible={modalOpen}
      onCancel={() => closeModal()}
      footer={null}
    >
      <Spin spinning={loading}>
        <Steps current={currentStep} labelPlacement="vertical">
          <Step
            title="上传文件"
            description={
              <p style={{ color: 'rgba(0,0,0,.45)', fontSize: '12px' }}>根据模板修改后上传</p>
            }
          />
          <Step
            title="导入数据"
            description={
              <p style={{ color: 'rgba(0,0,0,.45)', fontSize: '12px' }}>校验并导入数据</p>
            }
          />
          <Step
            title="导入成功"
            description={
              <p style={{ color: 'rgba(0,0,0,.45)', fontSize: '12px' }}>完成数据批量导入</p>
            }
          />
        </Steps>
        {currentStep === 0 && (
          <div style={{ marginTop: '16px' }}>
            <div style={{ margin: '16px 0', border: '1px solid rgba(0,0,0,.1)', padding: '16px' }}>
              <div>
                <p style={{ margin: '0px', fontWeight: 'bold' }}>填写导入车辆的信息</p>
                <p style={{ color: 'rgba(0,0,0,.55)', margin: '0px' }}>
                  请按照数据模板的格式准备导入数据，模板中的表头名称不可更改，表头行不能删除，单次导入的数据不超过1000条。
                </p>
                <a
                  onClick={() => {
                    downloadFileByUrl(templateUrl, '批量导入模板.xlsx');
                  }}
                  title="点击下载模板文件"
                >
                  下载模板
                </a>
              </div>
              <div style={{ marginTop: '16px' }}>
                <p style={{ margin: '0px', fontWeight: 'bold' }}>上传车辆数据表</p>
                <p style={{ color: 'rgba(0,0,0,.55)' }}>
                  文件后缀名必须为xls 或xlsx(即Excel格式)，文件大小不得大于5M
                </p>
              </div>
              <div style={{ marginTop: '16px' }}>
                <p style={{ margin: '0 30px 0 0', fontWeight: 'bold', display: 'inline' }}>
                  导入模式
                </p>
                <Radio.Group
                  onChange={(e: RadioChangeEvent) => setImportModel(e.target.value)}
                  value={importModel}
                >
                  <Radio value={0}>清空后新增数据</Radio>
                  <Radio value={1}>仅新增数据</Radio>
                </Radio.Group>
              </div>
            </div>
            <div>
              <Dragger {...uploadProps}>
                <p className="ant-upload-drag-icon">
                  <CloudUploadOutlined />
                </p>
                <p className="ant-upload-text">
                  将文件拖拽到此区域，或<a>点击添加</a>
                </p>
                <p className="ant-upload-hint">文件大小不得超过5Mb</p>
              </Dragger>
            </div>
            <div style={{ marginTop: '16px', display: 'flex', justifyContent: 'center' }}>
              <Button type="primary" onClick={handleNext}>
                下一步
              </Button>
            </div>
          </div>
        )}
        {currentStep === 1 && (
          <div style={{ marginTop: '16px' }}>
            <Result
              status="error"
              title={importResponse?.statusCode != '0' && importResponse?.statusMessage}
            >
              {importResponse?.data?.abnormalTotal && importResponse?.data?.abnormalTotal > 0 && (
                <div className="desc">
                  <Paragraph>
                    <Text strong>正常数量条数:</Text>
                    <Text
                      style={{
                        color: '#37c737',
                      }}
                    >
                      {importResponse?.data?.normalTotal}条
                    </Text>
                  </Paragraph>
                  <Paragraph>
                    <Text strong>异常数量条数:</Text>
                    <Text
                      style={{
                        color: '#e01135',
                      }}
                    >
                      {importResponse?.data?.abnormalTotal}条
                    </Text>
                  </Paragraph>
                  <Paragraph>
                    <p style={{ textAlign: 'right' }}>
                      <a
                        onClick={() => {
                          downloadFailureFile();
                        }}
                        title="下载失败原因文件"
                      >
                        下载失败原因文件&gt;&gt;
                      </a>
                    </p>
                  </Paragraph>
                </div>
              )}
            </Result>
            <div style={{ marginTop: '16px', display: 'flex', justifyContent: 'center' }}>
              <Button type="primary" onClick={handleRetry}>
                上一步
              </Button>
            </div>
          </div>
        )}
        {currentStep === 2 && (
          <div style={{ marginTop: '16px' }}>
            <Result
              status="success"
              title="数据导入完成"
              extra={[
                <Button type="primary" onClick={() => closeModal(true)}>
                  完成
                </Button>,
              ]}
            />
          </div>
        )}
      </Spin>
    </Modal>
  );
};

export default connect((state: any) => ({
  greyListMng: state.greyListMng,
}))(uploadModal);
